#include <iostream>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QTextStream>
#include <QTextCursor>
#include <QString>
#include <QDebug>
#include <stdio.h>
#include <QDateTime>
#include <alsa/asoundlib.h>


unsigned int vall;
int channels;
long loops;
QUdpSocket  *alsaudpSocket;   //套接字对象
snd_pcm_uframes_t  framess;    //帧大小


void alstThread::processPendingDatagram()
{
    while(alsaudpSocket->hasPendingDatagrams())  //拥有等待的数据报
       {
           QByteArray datagram; //拥于存放接收的数据报
           datagram.resize(alsaudpSocket->pendingDatagramSize());
           //让datagram的大小为等待处理的数据报的大小，这样才能接收到完整的数据
           alsaudpSocket->readDatagram(datagram.data(),datagram.size());
           //接收数据报，将其存放到datagram中

         //  ui->label->setText(datagram);
            qDebug()<<datagram;
           //将数据报内容显示出来
       }

}

void alstThread::alsa()
{
     alsaudpSocket = new QUdpSocket();
     int  rc;
     int  size;
     int file;
     snd_pcm_t*   handle;
     snd_pcm_hw_params_t*  params;
     snd_pcm_uframes_t  frames;    //帧大小
     int  dir;
     unsigned int val;
     char* buffer;
     alsaudpSocket->bind(prot,QUdpSocket::ShareAddress);
     qDebug()<<"prot"<<prot;
     connect(alsaudpSocket,SIGNAL(readyRead()),SLOT(processPendingDatagram())); //链接操函数

     if ( (rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE , 0)) < 0) //打开默认设备
     {
        std::cerr << "unable to open pcm device: " << snd_strerror(rc) << std::endl;
     }
    snd_pcm_hw_params_alloca(&params);//分配一个参数
    snd_pcm_hw_params_any(handle, params);//初始化参数
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); // 交互模式
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); //设置采样位数
    snd_pcm_hw_params_set_channels(handle, params, channels); //设置通道数
    val = vall; //采样率
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //函数设置音频数据的最接近目标的采样率 位
    frames = framess/4;//帧大小
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); //设置周期

    if ( (rc = snd_pcm_hw_params(handle, params)) < 0) //从设备配置空间选择一个配置
    {

            std::cerr << "unable to set hw paramseters: " << snd_strerror(rc) << std::endl;
            exit(1);

     }

     snd_pcm_hw_params_get_period_size(params, &frames, &dir);  //设置设置周期
     size = frames * 4;
     buffer = new char[size];
     snd_pcm_hw_params_get_period_time(params, &val, &dir);
     long count=0;
     file=open("/home/xiao/1.wav",O_RDWR ,777);
     if(file<0)
     {
         std::cerr <<"open file";
     }
     while (loops > 0)
     {

            rc = snd_pcm_readi(handle, buffer, frames); //读入一个数据
            if (rc == -EPIPE)
            {
                   std::cerr << "overrun occurred" << std::endl;
                   snd_pcm_prepare(handle);
            }
            else if (rc < 0)
                   std::cerr << "error from read: " << snd_strerror(rc) << std::endl;
            else if ( rc != (int)frames)
                   std::cerr << "short read, read " << rc << " frames" << std::endl;
           alsaudpSocket->writeDatagram(buffer,size,QHostAddress(ip_string),prot); //发送音频到端口
           rc= write(file, buffer,size);
             if (rc != size)
                std::cerr << "short write: wrote " << rc << " bytes" << std::endl;
            QDateTime time = QDateTime::currentDateTime();//获取系统现在的时间
            QString str = time.toString("hh:mm:ss zzz"); //设置显示格式
           // qDebug()<<"rc"<<rc<<"frames"<<frames<<"vall"<<vall<<"buf"<<count<<str;
            count++;

     }
     ::close(file);
     snd_pcm_drain(handle);
     snd_pcm_close(handle);
     free(buffer);
     delete alsaudpSocket;
}

void alstThread::run() //运行字子进程
{
    alsa();
}

void MainWindow::pushButton_alsa_ok(void)
{

    QString str = ui->lineEdit_ip->text();
    QString protc = ui->lineEdit_prot->text();
    strcpy(ip_string,str.toAscii().constData());
    prot = protc.toInt();
    str = ui->lineEdit_hz->text();
    vall = str.toInt(); //采样率
    str = ui->lineEdit_buf_sz->text();
    framess = str.toInt(); //采样率
    str= ui->lineEdit_channels->text();
    channels=  str.toInt(); //通道项目
    loops = 1;
    ALSA.start();
    ui->textEdit_udp->append("Cap start");
}

void MainWindow::pushButton_alsa_over(void)
{

    ui->textEdit_udp->append("alsa_over");
    loops = 0;
}



